#if defined(TSINGMA_MX) || defined(TSINGMA_GX) || defined(ARCTIC)
/**
 @file sys_tmm_linkagg.c

 @date 2018-9-21

 @version v1.0

 The file contains TMM Linkagg APIs of sys layer
*/

/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/

#include "sal.h"
#include "ctc_error.h"
#include "ctc_debug.h"
#include "ctc_register.h"
#include "sys_usw_register.h"
#include "sys_usw_common.h"
#include "sys_usw_chip.h"
#include "sys_usw_linkagg.h"
#include "sys_usw_dma.h"
#include "sys_usw_port_api.h"
#include "sys_usw_l2_fdb.h"
#include "sys_usw_nexthop_api.h"
#include "sys_usw_datapath.h"

#include "sys_tmm_linkagg.h"
#include "drv_api.h"

extern int32
_sys_usw_linkagg_remove_port_hw(uint8 lchip, sys_linkagg_t* p_group, uint32 gport);
extern int32
_sys_usw_linkagg_remove_db(uint8 lchip, uint16 tid);
extern uint32
_sys_usw_linkagg_driver2flows(uint8 lchip, uint8 driver_value, uint8 is_spm);
extern int32
_sys_usw_linkagg_get_ports2(uint8 lchip, sys_linkagg_t* p_group, uint32* member_list, uint8* p_member_cnt);
extern int32
_sys_usw_linkagg_get_pp_bmp(uint8 lchip, uint16 tid, uint16* pp_bmp);
extern int32
_sys_usw_linkagg_create_channel_agg(uint8 lchip, ctc_linkagg_group_t* p_linkagg_grp);
extern int32
_sys_usw_linkagg_destroy_channel_agg(uint8 lchip, uint8 tid);
extern int32
_sys_usw_linkagg_add_channel_member(uint8 lchip, uint8 tid, uint32 chan_id);
extern int32
_sys_usw_linkagg_remove_channel_member(uint8 lchip, uint8 tid, uint32 chan_id);

#define SYS_LINKAGG_PORT_BITMAP_IN_WORD ((MCHIP_CAP(SYS_CAP_PORT_NUM) + CTC_UINT32_BITS - 1 ) / CTC_UINT32_BITS)

int32
_sys_tmm_linkagg_update_nonuc_block_mask(uint8 lchip, sys_linkagg_t* p_group,
                                                            uint32* port_bitmap_old, uint32* port_bitmap_new, uint32 gport)
{
    uint16 loop = 0, loop2 = 0;
    uint16 mem_idx = 0;
    uint32* p_dma_mem = NULL;
    uint32 tbl_addr = 0;
    uint32* p_dma_mem_tmp = NULL;
    sys_dma_tbl_rw_t dma_cfg;
    uint16  lport = 0;
    int32  new_bitmap_cnt = 0;
    uint32* gports = NULL;
    int32 ret = CTC_E_NONE;
    uint8 entry_offset = TABLE_ENTRY_OFFSET(lchip, DsMetNonUcLagBlockMask_t);

    MALLOC_ZERO(MEM_LINKAGG_MODULE, gports, SYS_USW_MAX_PORT_NUM_PER_CHIP*sizeof(uint32));
    if (NULL == gports)
    {
        return CTC_E_NO_MEMORY;
    }
    for(mem_idx=0; (mem_idx<p_group->port_cnt) && (new_bitmap_cnt< SYS_USW_MAX_PORT_NUM_PER_CHIP); mem_idx++)
    {
        if (0 == p_group->port_list[mem_idx]->nonuc_block_en)
        {
            gports[new_bitmap_cnt] = p_group->port_list[mem_idx]->gport;
            new_bitmap_cnt++;
        }
    }

    sys_usw_dma_get_dma_memory(lchip, 0, &p_dma_mem);
    if (p_dma_mem)
    {
        /*1.set all old members block mask, 0 indicates pass*/
        for (loop = 0; (loop < SYS_LINKAGG_LB_HASH_MAX); loop++)
        {
            /* hash_value =  loop;
            gport, mask = 1 */
            p_dma_mem_tmp = (uint32*)((uint8 *)p_dma_mem + loop * entry_offset);

            if (port_bitmap_new)
            {
                for (loop2 = 0; loop2 < 8; loop2++)
                {
                    *((uint32*)((uint32*)p_dma_mem_tmp + loop2)) &= ~port_bitmap_old[loop2];
                    *((uint32*)((uint32*)p_dma_mem_tmp + loop2)) |= port_bitmap_new[loop2];
                }
            }
            else
            {
                if (sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(gport)))
                {
                    lport = CTC_MAP_GPORT_TO_LPORT(gport);
                    CTC_BMP_SET((uint32*)p_dma_mem_tmp, lport);
                }                
            }
            /*clear member need clear mask when use replace*/
            if(new_bitmap_cnt)
            {
                mem_idx = loop % new_bitmap_cnt;
                /*choose one port pass, to avoid repeat member blocked(replace)*/
                if (sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(gports[mem_idx])) &&
                    ((gports[mem_idx] != gport && !port_bitmap_new) || port_bitmap_new))
                {
                    CTC_BMP_UNSET((uint32*)p_dma_mem_tmp, CTC_MAP_GPORT_TO_LPORT(gports[mem_idx]) & 0xFFFF);
                }
            }

#if (SDB_DISABLE != SDB_MODE)
            drv_sdb_store(lchip, DsMetNonUcLagBlockMask_t, loop, p_dma_mem_tmp, TABLE_ENTRY_SIZE(lchip, DsMetNonUcLagBlockMask_t), 0);
#endif
        }

        /*4.write all  block entry  by DMA: DsMetNonUcLagBlockMask  */
        drv_usw_table_get_hw_addr(lchip, DsMetNonUcLagBlockMask_t, 0, &tbl_addr, FALSE);
        sal_memset(&dma_cfg, 0 , sizeof(sys_dma_tbl_rw_t));
        dma_cfg.tbl_addr = tbl_addr;
        dma_cfg.buffer = p_dma_mem;
        dma_cfg.entry_num = SYS_LINKAGG_LB_HASH_MAX;
        dma_cfg.entry_len = TABLE_ENTRY_SIZE(lchip, DsMetNonUcLagBlockMask_t);
        dma_cfg.user_dma_mode = 1;
        dma_cfg.entry_offset = TABLE_ENTRY_OFFSET(lchip, DsMetNonUcLagBlockMask_t);
        CTC_ERROR_GOTO(MCHIP_DMA(lchip)->dma_write_table(lchip, &dma_cfg), ret, error0);
    }
    else
    {
        uint32 cmd = 0;
        uint32 mask[CTC_PORT_BITMAP_IN_WORD] = {0};
        for (loop = 0; (loop < SYS_LINKAGG_LB_HASH_MAX); loop++)
        {
            /* hash_value =  loop*/
            cmd = DRV_IOR(DsMetNonUcLagBlockMask_t, DsMetNonUcLagBlockMask_blockPbmMask_f);
            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, loop, cmd, &mask), ret, error0);
            /*set all old members block mask, 0 indicates pass*/
            
            if (port_bitmap_new)
            {
                for (loop2 = 0; loop2 < SYS_LINKAGG_PORT_BITMAP_IN_WORD; loop2++)
                {
                    mask[loop2] &= ~port_bitmap_old[loop2];
                    mask[loop2] |= port_bitmap_new[loop2];
                }
            }
            else
            {
                if (sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(gport)))
                {
                    lport = CTC_MAP_GPORT_TO_LPORT(gport);
                    CTC_BMP_SET(mask, lport);
                }
            }
            /*clear member need clear mask when use replace*/
            if(new_bitmap_cnt)
            {
                mem_idx = loop % new_bitmap_cnt;
                /*choose one port pass, to avoid repeat member blocked(replace)*/
                if (sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(gports[mem_idx])) &&
                    ((gports[mem_idx] != gport && !port_bitmap_new) || port_bitmap_new))
                {
                    CTC_BMP_UNSET(mask,CTC_MAP_GPORT_TO_LPORT(gports[mem_idx]) & 0xFFFF);
                }
            }
            cmd = DRV_IOW(DsMetNonUcLagBlockMask_t, DsMetNonUcLagBlockMask_blockPbmMask_f);
            CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, loop, cmd, &mask), ret, error0);
        }
    }

error0:
    mem_free(gports);
    return ret;
}

int32
_sys_tmm_linkagg_clear_nonuc_ports(uint8 lchip, sys_linkagg_t* p_group)
{
    uint32 cmd = 0;
    uint32 port_bitmap_new[CTC_PORT_BITMAP_IN_WORD] = {0};
    uint32 port_bitmap_old[CTC_PORT_BITMAP_IN_WORD] = {0};
    sys_linkagg_t group_tmp;
    if(p_group->port_cnt == 0)
    {
        return 0;
    }

    /* clear nonuc ports only care tid and xfabric_en */
    sal_memset(&group_tmp, 0, sizeof(group_tmp));
    group_tmp.tid = p_group->tid;
    group_tmp.xfabric_type = p_group->xfabric_type;

    if (MCHIP_LAG(lchip)->update_nonuc_ports_by_pp && p_usw_linkagg_master[lchip]->xfabric_en)
    {
        /* clear bitmap do not care gport */
        CTC_ERROR_RETURN(MCHIP_LAG(lchip)->update_nonuc_ports_by_pp(lchip, &group_tmp, 0, port_bitmap_old, port_bitmap_new, SYS_LINKAGG_OP_CLR));
    }
    else
    {
        cmd = DRV_IOR(DsMetNonUcLagMemberBitmap_t, DsMetNonUcLagMemberBitmap_portBitmap_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, group_tmp.tid, cmd, port_bitmap_old));
    }

    /*clear bitmap*/
    sal_memset(port_bitmap_new, 0, sizeof(port_bitmap_new));
    cmd = DRV_IOW(DsMetNonUcLagMemberBitmap_t, DsMetNonUcLagMemberBitmap_portBitmap_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, group_tmp.tid, cmd, port_bitmap_new));

    /*linkagg and stacking share same table*/
    MCHIP_LAG_BLOCK_LOCK(lchip);
    _sys_tmm_linkagg_update_nonuc_block_mask(lchip, &group_tmp, port_bitmap_old, port_bitmap_new, 0);
    MCHIP_LAG_BLOCK_UNLOCK(lchip);

    return CTC_E_NONE;
}

int32
sys_tmm_linkagg_add_nonuc_ports(uint8 lchip, void* p_lag_group, uint32 gport, uint8 nonuc_block_en)
{
    uint32 cmd = 0;
    uint32  port_bitmap_old[CTC_PORT_BITMAP_IN_WORD] = {0};
    uint32  port_bitmap_new[CTC_PORT_BITMAP_IN_WORD] = {0};
    uint32  port_reflect_bmp[CTC_PORT_BITMAP_IN_WORD] = {0};
	int32   ret = 0;
    sys_linkagg_t* p_group = (sys_linkagg_t*)p_lag_group;

	/*if the gport nonuc_block_en, not need update block mask*/
    if (nonuc_block_en)
    {
        return CTC_E_NONE;
    }
	
    if (MCHIP_LAG(lchip)->update_nonuc_ports_by_pp && p_usw_linkagg_master[lchip]->xfabric_en)
    {
	 	/* keep bitmap unchange, only mask new add port */
		MCHIP_LAG_BLOCK_LOCK(lchip);
	    ret = _sys_tmm_linkagg_update_nonuc_block_mask(lchip, p_group, NULL, NULL, gport);
        ret = ret?ret:(MCHIP_LAG(lchip)->update_nonuc_ports_by_pp(lchip, p_group, gport, port_bitmap_old, port_bitmap_new, SYS_LINKAGG_OP_ADD));
    }
    else
    {
        cmd = DRV_IOR(DsMetNonUcLagMemberBitmap_t, DsMetNonUcLagMemberBitmap_portBitmap_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_group->tid, cmd, &port_bitmap_old));

        sal_memcpy(port_bitmap_new, port_bitmap_old, sizeof(port_bitmap_old));
        if (sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(gport)))
        {
            CTC_BMP_SET(port_bitmap_new, CTC_MAP_GPORT_TO_LPORT(gport));
        }

	    MCHIP_LAG_BLOCK_LOCK(lchip);
	    /*Step1: keep bitmap unchange, only mask new add port*/
	     ret = _sys_tmm_linkagg_update_nonuc_block_mask(lchip, p_group, port_bitmap_old, NULL, gport);

	    /*Step2: keep mask unchange, write bitmap */
	    cmd = DRV_IOW(DsMetNonUcLagMemberBitmap_t, DsMetNonUcLagMemberBitmap_portBitmap_f);
        ret = ret?ret:(DRV_FIELD_IOCTL(lchip, p_group->tid, cmd, &port_bitmap_new));
    }

    /*Step3: write real mask, to make new add port valid */
    /*linkagg and stacking share same table*/
    ret = ret?ret:_sys_tmm_linkagg_update_nonuc_block_mask(lchip, p_group, port_bitmap_old, port_bitmap_new, gport);
    MCHIP_LAG_BLOCK_UNLOCK(lchip);

    CTC_ERROR_RETURN(sys_usw_port_api_get_port_reflective(lchip, port_reflect_bmp));
    /*config the lag bitmap for first local member*/
    if(p_group->real_member_num == 1 && sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(gport)))
    {
        uint32 cmd;
        uint32 lag_bmp[CTC_PORT_BITMAP_IN_WORD] = {0};
        MetFifoHairPinCheckLag_m lag_check_bmp;

        cmd = DRV_IOR(MetFifoHairPinCheckLag_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_check_bmp));
        GetMetFifoHairPinCheckLag(A, lagBitmap_f, &lag_check_bmp, lag_bmp);

        if(CTC_BMP_ISSET(port_reflect_bmp, CTC_MAP_GPORT_TO_LPORT(gport)))
        {
            CTC_BMP_SET(lag_bmp, p_group->tid);
        }
        else
        {
            CTC_BMP_UNSET(lag_bmp, p_group->tid);
        }
        SetMetFifoHairPinCheckLag(A, lagBitmap_f, &lag_check_bmp, lag_bmp);
        cmd = DRV_IOW(MetFifoHairPinCheckLag_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_check_bmp));
    }
    return ret;
}

int32
sys_tmm_linkagg_remove_nonuc_ports(uint8 lchip, void* p_lag_group, uint32 gport, uint8 nonuc_block_en)
{
    uint32 cmd = 0;
    uint32  port_bitmap_old[CTC_PORT_BITMAP_IN_WORD] = {0};
    uint32  port_bitmap_new[CTC_PORT_BITMAP_IN_WORD] = {0};
	int32   ret = 0;
    sys_linkagg_t* p_group = (sys_linkagg_t*)p_lag_group;

	/*if the gport nonuc_block_en, not need update block mask*/
    if (nonuc_block_en)
    {
        return CTC_E_NONE;
    }
	
    if (MCHIP_LAG(lchip)->update_nonuc_ports_by_pp && p_usw_linkagg_master[lchip]->xfabric_en)
    {
		/* keep bitmap unchange, only mask new add port */
		MCHIP_LAG_BLOCK_LOCK(lchip);
	    ret = _sys_tmm_linkagg_update_nonuc_block_mask(lchip, p_group, NULL, NULL, gport);
        ret = ret?ret:(MCHIP_LAG(lchip)->update_nonuc_ports_by_pp(lchip, p_group, gport, port_bitmap_old, port_bitmap_new, SYS_LINKAGG_OP_DEL));
    }
    else
    {
        cmd = DRV_IOR(DsMetNonUcLagMemberBitmap_t, DsMetNonUcLagMemberBitmap_portBitmap_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_group->tid, cmd, &port_bitmap_old));

        sal_memcpy(port_bitmap_new, port_bitmap_old, sizeof(port_bitmap_old));
        if (sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(gport)))
        {
            CTC_BMP_UNSET(port_bitmap_new, CTC_MAP_GPORT_TO_LPORT(gport));
        }

	    MCHIP_LAG_BLOCK_LOCK(lchip);
	    /*Step1: keep bitmap unchange, only mask remove port*/
	    ret = _sys_tmm_linkagg_update_nonuc_block_mask(lchip, p_group, port_bitmap_old, NULL, gport);

	    /*Step2: keep mask unchange, write bitmap */
	    cmd = DRV_IOW(DsMetNonUcLagMemberBitmap_t, DsMetNonUcLagMemberBitmap_portBitmap_f);
	    ret = ret?ret:(DRV_FIELD_IOCTL(lchip, p_group->tid, cmd, port_bitmap_new));
    }

    /*Step3: write real mask, to make new remove port invalid */
    /*linkagg and stacking share same table*/
    ret = ret?ret:_sys_tmm_linkagg_update_nonuc_block_mask(lchip, p_group, port_bitmap_old, port_bitmap_new, gport);
    MCHIP_LAG_BLOCK_UNLOCK(lchip);
   
    return ret;
}

int32
sys_tmm_linkagg_replace_nonuc_ports(uint8 lchip, void* p_lag_group)
{
    uint32 cmd = 0;
    uint32  port_bitmap_old[CTC_PORT_BITMAP_IN_WORD] = {0};
    uint32  port_bitmap_new[CTC_PORT_BITMAP_IN_WORD] = {0};
    uint32  port_reflect_bmp[CTC_PORT_BITMAP_IN_WORD] = {0};
    uint16 index = 0;
    sys_linkagg_t* p_group = (sys_linkagg_t*)p_lag_group;
    int32 ret = CTC_E_NONE;

    MCHIP_LAG_BLOCK_LOCK(lchip);
    cmd = DRV_IOR(DsMetNonUcLagMemberBitmap_t, DsMetNonUcLagMemberBitmap_portBitmap_f);
    ret = DRV_FIELD_IOCTL(lchip, p_group->tid, cmd, &port_bitmap_old);

    for(index = 0; index < p_group->port_cnt; index++)
    {
        if (sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(p_group->port_list[index]->gport))
            && (0 == p_group->port_list[index]->nonuc_block_en))
        {
            CTC_BMP_SET(port_bitmap_new, CTC_MAP_GPORT_TO_LPORT(p_group->port_list[index]->gport) & 0xFF);
        }
    }
    if (MCHIP_LAG(lchip)->update_nonuc_ports_by_pp && p_usw_linkagg_master[lchip]->xfabric_en)
    {
        /* replace do not care gport */
        ret = ret?ret:MCHIP_LAG(lchip)->update_nonuc_ports_by_pp(lchip, p_group, 0, port_bitmap_old, port_bitmap_new, SYS_LINKAGG_OP_REP);
    }
    else
    {
		/*Step2: keep mask unchange, write bitmap */
        cmd = DRV_IOW(DsMetNonUcLagMemberBitmap_t, DsMetNonUcLagMemberBitmap_portBitmap_f);
    	ret = ret?ret:(DRV_FIELD_IOCTL(lchip, p_group->tid, cmd, port_bitmap_new));
    }

    /*Step3: write real mask, to make new add port valid */
    /*linkagg and stacking share same table*/
    ret = ret?ret:_sys_tmm_linkagg_update_nonuc_block_mask(lchip, p_group, port_bitmap_old, port_bitmap_new, 0);
    MCHIP_LAG_BLOCK_UNLOCK(lchip);
    CTC_ERROR_RETURN(ret);

    CTC_ERROR_RETURN(sys_usw_port_api_get_port_reflective(lchip, port_reflect_bmp));
    /*config the lag bitmap for first local member*/
    if(p_group->port_cnt && sys_usw_chip_is_local(lchip, SYS_MAP_CTC_GPORT_TO_GCHIP(p_group->port_list[0]->gport)))
    {
        uint32 lag_bmp[CTC_PORT_BITMAP_IN_WORD] = {0};
        MetFifoHairPinCheckLag_m lag_check_bmp;

        cmd = DRV_IOR(MetFifoHairPinCheckLag_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_check_bmp));
        GetMetFifoHairPinCheckLag(A, lagBitmap_f, &lag_check_bmp, lag_bmp);

        if(CTC_BMP_ISSET(port_reflect_bmp, CTC_MAP_GPORT_TO_LPORT(p_group->port_list[0]->gport)))
        {
            CTC_BMP_SET(lag_bmp, p_group->tid);
        }
        else
        {
            CTC_BMP_UNSET(lag_bmp, p_group->tid);
        }
        SetMetFifoHairPinCheckLag(A, lagBitmap_f, &lag_check_bmp, lag_bmp);
        cmd = DRV_IOW(MetFifoHairPinCheckLag_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_check_bmp));
    }
    return ret;
}

int32
sys_tmm_linkagg_destroy(uint8 lchip, void* p_lag_group)
{
    uint16 mem_idx = 0;
    uint16 real_member_num = 0;
    uint32 cmd = 0;
    DsLinkAggregateGroup_m ds_linkagg_group;
    sys_linkagg_t* p_group = (sys_linkagg_t*)p_lag_group;
    sys_linkagg_t* p_nonuc_group = NULL;
    uint32  member_port= 0;
    ctc_linkagg_lsh_t port_array;

    /*sanity check*/
    sal_memset(&ds_linkagg_group, 0, sizeof(ds_linkagg_group));
    if (CTC_FLAG_ISSET(p_group->flag, CTC_LINKAGG_GROUP_FLAG_NONUC_DETACH))
    {
        p_nonuc_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, p_group->tid+MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM));
    }

    real_member_num = p_group->real_member_num;
    for (mem_idx = 0; mem_idx < real_member_num; mem_idx++)
    {
        if(!p_group->port_list[mem_idx])
        {
            continue;
        }
        member_port = p_group->port_list[mem_idx]->gport;
        if(p_group->mode == CTC_LINKAGG_MODE_DLB)
        {
            CTC_ERROR_DUMP(_sys_usw_linkagg_remove_port_hw(lchip, p_group, member_port));
        }

        if (TRUE == sys_usw_chip_is_local(lchip, CTC_MAP_GPORT_TO_GCHIP(member_port)))
        {
            sys_usw_port_api_update_mc_linkagg(lchip, p_group->tid, CTC_MAP_GPORT_TO_LPORT(member_port), 0);
            /*set local port's global_port*/
            if (!p_usw_linkagg_master[lchip]->bind_gport_disable)
            {
                sys_usw_port_api_set_global_port(lchip, CTC_MAP_GPORT_TO_LPORT(member_port), member_port, FALSE);
            }
        }

        /*clean backup ports for the port which will be remove*/
        if (MCHIP_LAG(lchip)->set_lsh)
        {
            sal_memset(&port_array, 0, sizeof(port_array));
            sys_tmm_linkagg_set_lsh(lchip, p_group, member_port, &port_array);
        }
    }

    if (p_nonuc_group)
    {
        for (mem_idx = 0; mem_idx < p_nonuc_group->port_cnt; mem_idx++)
        {
            if(!p_nonuc_group->port_list[mem_idx])
            {
                continue;
            }
            member_port = p_nonuc_group->port_list[mem_idx]->gport;
            if (TRUE == sys_usw_chip_is_local(lchip, CTC_MAP_GPORT_TO_GCHIP(member_port)))
            {
                sys_usw_port_update_mc_linkagg(lchip, p_nonuc_group->tid, CTC_MAP_GPORT_TO_LPORT(member_port), 0);
            }
        }
        _sys_tmm_linkagg_clear_nonuc_ports(lchip, p_nonuc_group);
        _sys_usw_linkagg_remove_db(lchip, p_nonuc_group->tid+MCHIP_CAP(SYS_CAP_LINKAGG_GROUP_NUM));
    }
    else
    {
        _sys_tmm_linkagg_clear_nonuc_ports(lchip, p_group);
    }

    if(p_group->flag & CTC_LINKAGG_GROUP_FLAG_SPM_EN)
    {
        uint32 cmd = 0;
        uint32 antflow_base = 0;
        uint32 flow_num = 0;
        cmd = DRV_IOR(DsLinkAggregateGroup_t, DsLinkAggregateGroup_antFlowTableBase_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_group->tid, cmd, &antflow_base));
        cmd = DRV_IOR(DsLinkAggregateGroup_t, DsLinkAggregateGroup_linkAggFlowNum_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_group->tid, cmd, &flow_num));
        sys_usw_ftm_free_table_offset(lchip, DsAntFlow_t, 0, _sys_usw_linkagg_driver2flows(lchip, flow_num, 1),
                                        antflow_base << SYS_LINKAGG_SPM_TBL_BASE_WIDTH);
    }

    /*reset linkagg group */
    cmd = DRV_IOW(DsLinkAggregateGroup_t, DRV_ENTRY_FLAG);
    DRV_IOCTL(lchip, p_group->tid, cmd, &ds_linkagg_group);
    sys_usw_l2_set_dsmac(lchip, CTC_MAP_TID_TO_GPORT(p_group->tid), FALSE);
    if(p_group->mode == CTC_LINKAGG_MODE_RR)
    {
        uint32 rr_profile_id = 0;
        cmd = DRV_IOR(LagRrProfileIdMappingCtl_t, LagRrProfileIdMappingCtl_rrProfileId_f);
        DRV_FIELD_IOCTL(lchip, p_group->tid, cmd, &rr_profile_id);
        CTC_BIT_UNSET(p_usw_linkagg_master[lchip]->rr_profile_bmp, rr_profile_id);
    }
    if(MCHIP_LAG(lchip)->update_mirror_dest)
    {
        MCHIP_LAG(lchip)->update_mirror_dest(lchip, p_group->tid, 0);
    }
    sys_usw_brguc_nh_delete(lchip, CTC_MAP_TID_TO_GPORT(p_group->tid));
    _sys_usw_linkagg_remove_db(lchip, p_group->tid);
    return CTC_E_NONE;
}

int32
_sys_tmm_linkagg_dlb_set_quality_map(uint8 lchip, uint8 tx_load_percent)
{
    uint32 cmd = 0;
    uint32 entry_index = 0;
    uint8 quantized_tx_load = 0;
    uint8 quantized_qsize = 0;
    uint32 quality = 0;

    for (quantized_tx_load = 0; quantized_tx_load < 16; quantized_tx_load++) {
        for (quantized_qsize = 0; quantized_qsize < 16; quantized_qsize++) {
            quality = (quantized_tx_load * tx_load_percent +
                    quantized_qsize * (100 - tx_load_percent)) / 100;
            entry_index = (quantized_tx_load << 4) + quantized_qsize;
            cmd = DRV_IOW(LagDlbQualityMapCtl_t, LagDlbQualityMapCtl_quality_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, entry_index, cmd, &quality));
            cmd = DRV_IOW(EcmpDlbQualityMapCtl_t, EcmpDlbQualityMapCtl_quality_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, entry_index, cmd, &quality)); 
        }
    }

    p_usw_linkagg_master[lchip]->tx_load_percent = tx_load_percent;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MASTER, 1);

    return CTC_E_NONE;
}

int32
_sys_tmm_linkagg_dlb_set_load_quality_threshold(uint8 lchip, uint32 min_th, uint32 max_th)
{
    uint32 cmd = 0;
    uint32 th_bytes = 0;
    uint32 th_step = 0;
    uint32 factors[] = { 1, 5, 10, 20, 25, 40, 50, 100};
    uint8 i = 0;
    uint8 j = 0;
    LagDlbChanLoadQuantizeThreshold_m lag_dlb_load_threshold;

    if (min_th > max_th) {
        max_th = min_th;
    }

    if (max_th * factors[7] > 0xffffff) {
        /* Hardware limits load size threshold to 24 bits */
        return CTC_E_INVALID_PARAM;
    }

    for(i = 0; i < 8; i++)
    {
        sal_memset(&lag_dlb_load_threshold, 0, sizeof(lag_dlb_load_threshold));

        th_step = (max_th - min_th)  / 14;
        for (j = 0; j < 15; j++)
        {
            th_bytes = (min_th + j * th_step) * factors[i];
            SetLagDlbChanLoadQuantizeThreshold(V, gProfile_0_chanLoadThreshold_f + j, &lag_dlb_load_threshold, th_bytes);
        }

        cmd = DRV_IOW(LagDlbChanLoadQuantizeThreshold_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, i, cmd, &lag_dlb_load_threshold));
    }

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MASTER, 1);

    return CTC_E_NONE;
}

int32
_sys_tmm_linkagg_dlb_set_qdepth_quality_threshold(uint8 lchip, uint32 min_th, uint32 max_th)
{
    uint32 cmd = 0;
    uint32 th_cells = 0;
    uint32 th_step = 0;
    uint32 factors[] = { 1, 5, 10, 20, 25, 40, 50, 100};
    uint8 i = 0;
    uint8 j = 0;
    LagDlbChanQdepthQuantizeThreshold_m lag_dlb_qdepth_threshold;

    if (min_th > max_th) {
        max_th = min_th;
    }

    if (max_th * factors[7] > 0x1ffff) {
        /* Hardware limits queue depth threshold to 17 bits */
        return CTC_E_INVALID_PARAM;
    }

    for (i = 0; i < 8; i++)
    {
        sal_memset(&lag_dlb_qdepth_threshold, 0, sizeof(lag_dlb_qdepth_threshold));

        th_step = (max_th - min_th)  / 14;
        for (j = 0; j < 15; j++)
        {
            th_cells = (min_th + j * th_step) * factors[i];
            SetLagDlbChanQdepthQuantizeThreshold(V, gProfile_0_queueDepthThreshold_f + j, &lag_dlb_qdepth_threshold, th_cells);
        }

        cmd = DRV_IOW(LagDlbChanQdepthQuantizeThreshold_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, i, cmd, &lag_dlb_qdepth_threshold));
    }

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_LINKAGG, SYS_WB_APPID_LINKAGG_SUBID_MASTER, 1);

    return CTC_E_NONE;
}

int32
sys_tmm_linkagg_dlb_init(uint8 lchip)
{
    uint32 value = 0;
    uint32 cmd = 0;
    uint32 tx_load_percent = 0;
    uint16 i = 0;
    uint16 chan_id = 0;
    uint8  step = 0;

    LagDlbQualityMapCtl_m lag_dlb_quality_map_ctl;
    LagEngineChanAvgLoadTimerCtl_m lag_engine_avg_load_ctl;
    LagEngineChanAvgQdepthTimerCtl_m  lag_engine_avg_qdepth_ctl;
    LagEngineDlbCtl_m lag_engine_dlb_ctl;
    LagEngineCtl_m lag_engine_ctl;

    sal_memset(&lag_dlb_quality_map_ctl, 0, sizeof(lag_dlb_quality_map_ctl));
    sal_memset(&lag_engine_avg_load_ctl, 0, sizeof(lag_engine_avg_load_ctl));
    sal_memset(&lag_engine_avg_qdepth_ctl, 0, sizeof(lag_engine_avg_qdepth_ctl));
    sal_memset(&lag_engine_dlb_ctl, 0, sizeof(lag_engine_dlb_ctl));
    sal_memset(&lag_engine_ctl, 0, sizeof(lag_engine_ctl));

    /*1.config LagDlbQualityMapCtl_m*/
    tx_load_percent = 100;
    CTC_ERROR_RETURN(_sys_tmm_linkagg_dlb_set_quality_map(lchip, tx_load_percent));

    /*2.config LagDlbChanLoadType & LagDlbChanQueueDepthType_m*/
    for (i = 0; i < MCHIP_CAP(SYS_CAP_CHANNEL_NUM); i++)
    {
        CTC_ERROR_RETURN(sys_usw_dmps_set_dlb_chan_type(lchip, i));
    }

    /*3.config LagEngineChanAvgLoadTimerCtl_m*/
    SetLagEngineChanAvgLoadTimerCtl(V, chanLoadUpdEn_f, &lag_engine_avg_load_ctl, 1);
    SetLagEngineChanAvgLoadTimerCtl(V, chanLoadInterval_f, &lag_engine_avg_load_ctl, 1);
    SetLagEngineChanAvgLoadTimerCtl(V, dreOptimizeEnable_f, &lag_engine_avg_load_ctl, 0);
    SetLagEngineChanAvgLoadTimerCtl(V, ewmaChanLoadWeight_f, &lag_engine_avg_load_ctl, 0);
    SetLagEngineChanAvgLoadTimerCtl(V, ewmaMode_f, &lag_engine_avg_load_ctl, 0);
    SetLagEngineChanAvgLoadTimerCtl(V, syncBandwidthToEcmpEn_f, &lag_engine_avg_load_ctl, 1);
    SetLagEngineChanAvgLoadTimerCtl(V, syncBandwidthToEpeEn_f, &lag_engine_avg_load_ctl, 1);
    SetLagEngineChanAvgLoadTimerCtl(V, syncBandwidthToOtherCoreEn_f, &lag_engine_avg_load_ctl, 1);

    /* Rp = 1/(2^chanDreDiscountShift) = 1/2 */
    step = LagEngineChanAvgLoadTimerCtl_array_1_chanDreDiscountShift_f - LagEngineChanAvgLoadTimerCtl_array_0_chanDreDiscountShift_f;
    for (i = 0; i < MCHIP_CAP(SYS_CAP_CHANNEL_NUM); i++)
    {
        uint16 chan_tmp = SYS_USW_CHANNEL_ENCODE(i);
        SetLagEngineChanAvgLoadTimerCtl(V, array_0_chanDreDiscountShift_f + chan_tmp * step, &lag_engine_avg_load_ctl, 1);
    }

    cmd = DRV_IOW(LagEngineChanAvgLoadTimerCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_engine_avg_load_ctl));
    /* Config load pulse timer for Tp=1us, [30:8] pulse : [7:0] pulse_frac */
    value = (1 * 156250 / 1000) << 8 | (1 * 156250 % 1000 * 256 / 1000); /* value=40000   */
    cmd = DRV_IOW(RefDivLagEnginePulse_t, RefDivLagEnginePulse_cfgRefDivLagEngineChanAvgLoadPulse_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    value = 0;
    cmd = DRV_IOW(RefDivLagEnginePulse_t, RefDivLagEnginePulse_cfgResetDivLagEngineChanAvgLoadPulse_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));


    /*4.config LagDlbChanLoadQuantizeThreshold_m*/
    /*sample period 1us in 1G speed, when 5G speed, need multiply the fator 5.
      quality  Threshold(bytes)
      0        120 ~ 125
      1        112 ~ 120
      2        104 ~ 112
      3        96  ~ 104
      4        88  ~ 96
      5        80  ~ 88
      6        72  ~ 80
      7        64  ~ 72
      8        56  ~ 64
      9        48  ~ 56
      10       40  ~ 48
      11       32  ~ 40
      12       24  ~ 32
      13       16  ~ 24
      14       8   ~ 16
      15       0   ~ 8
    */
    CTC_ERROR_RETURN(_sys_tmm_linkagg_dlb_set_load_quality_threshold(lchip, 8, 120));/*max 12500*/

    /*5.config LagEngineChanAvgQdepthTimerCtl_m*/
    SetLagEngineChanAvgQdepthTimerCtl(V, chanQdepthInterval_f, &lag_engine_avg_qdepth_ctl, 1);
    SetLagEngineChanAvgQdepthTimerCtl(V, chanQdepthUpdEn_f, &lag_engine_avg_qdepth_ctl, 1);
    SetLagEngineChanAvgQdepthTimerCtl(V, ewmaChanQdepthMode_f, &lag_engine_avg_qdepth_ctl, 0);
    SetLagEngineChanAvgQdepthTimerCtl(V, ewmaChanQdepthWeight_f, &lag_engine_avg_qdepth_ctl, 0);
    SetLagEngineChanAvgQdepthTimerCtl(V, syncQdepthToEcmpEn_f, &lag_engine_avg_qdepth_ctl, 1);
    SetLagEngineChanAvgQdepthTimerCtl(V, syncQdepthToOtherCoreEn_f, &lag_engine_avg_qdepth_ctl, 1);

    cmd = DRV_IOW(LagEngineChanAvgQdepthTimerCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_engine_avg_qdepth_ctl));

    /* Config load pulse timer for Tp=1us, [30:8] pulse : [7:0] pulse_frac */
    value = (1 * 156250 / 1000) << 8 | (1 * 156250 % 1000 * 256 / 1000);   /* value=40000  */
    cmd = DRV_IOW(RefDivLagEnginePulse_t, RefDivLagEnginePulse_cfgRefDivLagEngineChanAvgQSizePulse_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));
    value = 0;
    cmd = DRV_IOW(RefDivLagEnginePulse_t, RefDivLagEnginePulse_cfgResetDivLagEngineChanAvgQSizePulse_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &value));

    /*6.config LagDlbChanQdepthQuantizeThreshold_m*/
    CTC_ERROR_RETURN(_sys_tmm_linkagg_dlb_set_qdepth_quality_threshold(lchip, 0, MCHIP_CAP(SYS_CAP_QOS_QUEUE_MAX_DROP_THRD)/100));

    /*7.config LagEngineDlbCtl_m*/
    cmd = DRV_IOR(LagEngineDlbCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_engine_dlb_ctl));

    SetLagEngineDlbCtl(V, dlbEn_f, &lag_engine_dlb_ctl, 1);
    SetLagEngineDlbCtl(V, byteCountShift_f, &lag_engine_dlb_ctl, 0);  /* unit of dre counter */
    SetLagEngineDlbCtl(V, ipg_f, &lag_engine_dlb_ctl, 0);     /* for dre ipg */
    SetLagEngineDlbCtl(V, chanHisLoadUpdateMode_f, &lag_engine_dlb_ctl, 0); /* default dre;0:dre 1:ewma*/
    SetLagEngineDlbCtl(V, mySliceId_f, &lag_engine_dlb_ctl, 0);

    cmd = DRV_IOW(LagEngineDlbCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_engine_dlb_ctl));

    /*8.config LagEngineCtl_m*/
    cmd = DRV_IOR(LagEngineCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_engine_ctl));

    SetLagEngineCtl(V, portLagMemberMoveCheckEn_f, &lag_engine_ctl, 3);
    SetLagEngineCtl(V, rrProtectDisable_f,&lag_engine_ctl, 0);
    SetLagEngineCtl(V, iLoopOamDestId_f, &lag_engine_ctl, SYS_RSV_PORT_ILOOP_ID);

    cmd = DRV_IOW(LagEngineCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &lag_engine_ctl));

    value = 1;
    cmd = DRV_IOW(LagEngineLinkState_t, LagEngineLinkState_linkState_f);
    for(chan_id=0; chan_id < MCHIP_CAP(SYS_CAP_CHANNEL_NUM); chan_id++)
    {
        if (!SYS_IS_NETWORK_CHANNEL(chan_id))
        {
            continue;
        }
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &value));
    }
    return CTC_E_NONE;
}

int32
sys_tmm_linkagg_dlb_set_config(uint8 lchip, void* p_cfg)
{
    uint32 cmd = 0;
    uint32 field_val = 0;
    uint16 chan_id = 0;
    uint16 step = 0;
    ctc_global_lag_dlb_property_t* p_dlb_cfg = (ctc_global_lag_dlb_property_t*)p_cfg;
    ds1_t ds;

    SYS_LINKAGG_INIT_CHECK();
    CTC_PTR_VALID_CHECK(p_dlb_cfg);
    CTC_MAX_VALUE_CHECK(p_dlb_cfg->mode, CTC_LAG_DLB_MODE_MAX - 1);
    CTC_MAX_VALUE_CHECK(p_dlb_cfg->port_weight, 0xF);
    CTC_MAX_VALUE_CHECK(p_dlb_cfg->queue_weight, 0xF);
    CTC_MAX_VALUE_CHECK(p_dlb_cfg->queue_percent, 100);
    CTC_MAX_VALUE_CHECK((p_dlb_cfg->interval * 156250 / 1000), 0x7FFFFF);

    /*check mode*/
    switch (p_dlb_cfg->mode)
    {
        case CTC_LAG_DLB_MODE_PORT:
            if (0 != p_dlb_cfg->queue_percent)
            {
                return CTC_E_INVALID_PARAM;
            }
            break;
        case CTC_LAG_DLB_MODE_QUEUE:
            if (!p_dlb_cfg->calc_type || 100 != p_dlb_cfg->queue_percent)
            {
                return CTC_E_INVALID_PARAM;
            }
            break;
        case CTC_LAG_DLB_MODE_PORT_QUEUE:
            if (!p_dlb_cfg->calc_type
                || 100 == p_dlb_cfg->queue_percent
                || 0 == p_dlb_cfg->queue_percent)
            {
                return CTC_E_INVALID_PARAM;
            }
            break;
        default:
            return CTC_E_INVALID_PARAM;
    }

    if(p_dlb_cfg->interval)
    {
        CTC_ERROR_RETURN(_sys_tmm_linkagg_dlb_set_load_quality_threshold(lchip, 8 * p_dlb_cfg->interval, 120 * p_dlb_cfg->interval));
            
        /* Config load pulse timer for Tp, [30:8] pulse : [7:0] pulse_frac */
        field_val = (p_dlb_cfg->interval * 156250 / 1000) << 8 | (p_dlb_cfg->interval * 156250 % 1000 * 256 / 1000);
        cmd = DRV_IOR(RefDivLagEnginePulse_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
        if (p_dlb_cfg->mode == CTC_LAG_DLB_MODE_PORT || p_dlb_cfg->mode == CTC_LAG_DLB_MODE_PORT_QUEUE)
        {
            SetRefDivLagEnginePulse(V, cfgRefDivLagEngineChanAvgLoadPulse_f, &ds, field_val);
            SetRefDivLagEnginePulse(V, cfgResetDivLagEngineChanAvgLoadPulse_f, &ds, 0);
        }
        if (p_dlb_cfg->mode == CTC_LAG_DLB_MODE_QUEUE || p_dlb_cfg->mode == CTC_LAG_DLB_MODE_PORT_QUEUE)
        {
            SetRefDivLagEnginePulse(V, cfgRefDivLagEngineChanAvgQSizePulse_f, &ds, field_val);
            SetRefDivLagEnginePulse(V, cfgResetDivLagEngineChanAvgQSizePulse_f, &ds, 0);
        }
        cmd = DRV_IOW(RefDivLagEnginePulse_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    }

    /*config ewma enable*/
    cmd = DRV_IOR(LagEngineDlbCtl_t, LagEngineDlbCtl_chanHisLoadUpdateMode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    if (field_val != p_dlb_cfg->calc_type)
    {
        field_val = p_dlb_cfg->calc_type ? 1 : 0;
        cmd = DRV_IOW(LagEngineDlbCtl_t, LagEngineDlbCtl_chanHisLoadUpdateMode_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

        /*clear state*/
        field_val = 0;
        for(chan_id=0; chan_id < MCHIP_CAP(SYS_CAP_CHANNEL_NUM); chan_id++)
        {
            cmd = DRV_IOW(LagDlbChanLoadQualityS0_t, LagDlbChanLoadQualityS0_chanLoadQuality_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));

            cmd = DRV_IOW(LagEngineChannelByteCounterCurS0_t, LagEngineChannelByteCounterCurS0_byteCount_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));

            cmd = DRV_IOW(LagEngineChannelByteCounterHisS0_t, LagEngineChannelByteCounterHisS0_dreCount_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));

            cmd = DRV_IOW(EcmpDlbChanLoadQualityS0_t, EcmpDlbChanLoadQualityS0_chanLoadQuality_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, chan_id, cmd, &field_val));
        }
    }

    if (p_dlb_cfg->calc_type)
    {
        /*config load ewma weight*/
        field_val = p_dlb_cfg->port_weight;
        cmd = DRV_IOW(LagEngineChanAvgLoadTimerCtl_t, LagEngineChanAvgLoadTimerCtl_ewmaChanLoadWeight_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

        /*config qdepth ewma weight*/
        field_val = p_dlb_cfg->queue_weight;
        cmd = DRV_IOW(LagEngineChanAvgQdepthTimerCtl_t, LagEngineChanAvgQdepthTimerCtl_ewmaChanQdepthWeight_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    }
    else
    {
        /*config load dre shift*/
        step = LagEngineChanAvgLoadTimerCtl_array_1_chanDreDiscountShift_f - LagEngineChanAvgLoadTimerCtl_array_0_chanDreDiscountShift_f;
        cmd = DRV_IOR(LagEngineChanAvgLoadTimerCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
        for (chan_id = 0; chan_id < MCHIP_CAP(SYS_CAP_CHANNEL_NUM); chan_id++)
        {
            uint16 chan_tmp = SYS_USW_CHANNEL_ENCODE(chan_id);
            SetLagEngineChanAvgLoadTimerCtl(V, array_0_chanDreDiscountShift_f + step * chan_tmp, &ds, p_dlb_cfg->port_weight);
        }
        cmd = DRV_IOW(LagEngineChanAvgLoadTimerCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    }

    /*config quality mapping*/
    CTC_ERROR_RETURN(_sys_tmm_linkagg_dlb_set_quality_map(lchip, 100 - p_dlb_cfg->queue_percent));

    return CTC_E_NONE;
}

int32
sys_tmm_linkagg_dlb_get_config(uint8 lchip, void* p_cfg)
{
    uint32 cmd = 0;
    uint32 field_val = 0;
    ctc_global_lag_dlb_property_t* p_dlb_cfg = 0;
    ds_t ds;

    SYS_LINKAGG_INIT_CHECK();
    p_dlb_cfg = (ctc_global_lag_dlb_property_t*)p_cfg;
    
    CTC_PTR_VALID_CHECK(p_dlb_cfg);

    if (100 == p_usw_linkagg_master[lchip]->tx_load_percent)
    {
        p_dlb_cfg->mode = CTC_LAG_DLB_MODE_PORT;
    }
    else if (0 == p_usw_linkagg_master[lchip]->tx_load_percent)
    {
        p_dlb_cfg->mode = CTC_LAG_DLB_MODE_QUEUE;
    }
    else
    {
        p_dlb_cfg->mode = CTC_LAG_DLB_MODE_PORT_QUEUE;
    }

    /*get Tp*/
    cmd = DRV_IOR(RefDivLagEnginePulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    if (p_dlb_cfg->mode == CTC_LAG_DLB_MODE_PORT || p_dlb_cfg->mode == CTC_LAG_DLB_MODE_PORT_QUEUE)
    {
        field_val = GetRefDivLagEnginePulse(V, cfgRefDivLagEngineChanAvgLoadPulse_f, &ds);
    }
    if (p_dlb_cfg->mode == CTC_LAG_DLB_MODE_QUEUE || p_dlb_cfg->mode == CTC_LAG_DLB_MODE_PORT_QUEUE)
    {
        field_val = GetRefDivLagEnginePulse(V, cfgRefDivLagEngineChanAvgQSizePulse_f, &ds);
    }
    p_dlb_cfg->interval = ((field_val >> 8) * 1000 + (field_val & 0xFF) * 1000 / 256) / 156250;
 
    /*get ewma enable*/
    cmd = DRV_IOR(LagEngineDlbCtl_t, LagEngineDlbCtl_chanHisLoadUpdateMode_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
    p_dlb_cfg->calc_type = field_val ? 1 : 0;

    if (p_dlb_cfg->calc_type)
    {
        /*get load ewma weight*/
        cmd = DRV_IOR(LagEngineChanAvgLoadTimerCtl_t, LagEngineChanAvgLoadTimerCtl_ewmaChanLoadWeight_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
        p_dlb_cfg->port_weight = field_val;

        /*get qdepth ewma weight*/
        cmd = DRV_IOR(LagEngineChanAvgQdepthTimerCtl_t, LagEngineChanAvgQdepthTimerCtl_ewmaChanQdepthWeight_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
        p_dlb_cfg->queue_weight = field_val;
    }
    else
    {
        cmd = DRV_IOR(LagEngineChanAvgLoadTimerCtl_t, LagEngineChanAvgLoadTimerCtl_array_0_chanDreDiscountShift_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));
        p_dlb_cfg->port_weight = field_val;
    }

    /*get quality mapping*/
    p_dlb_cfg->queue_percent = 100 - p_usw_linkagg_master[lchip]->tx_load_percent;

    return CTC_E_NONE;
}

STATIC int32
_sys_tmm_linkagg_lsh_add_to_asic(uint8 lchip, uint32 fail_port, ctc_linkagg_lsh_t* port_array)
{
    DsMetPortLagLinkSelfHealingSet_m    nouc_self_healing;
    PortLagLinkSelfHealingSet_m            uc_self_healing;
    DsMetExcpPortLagLinkSelfHealingSet_m excp_self_healing;
    uint32 uc_cmdr = 0;
    uint32 uc_cmdw = 0;
    uint32 uc_en_cmdr = 0;
    uint32 uc_en_cmdw = 0;
    uint32 nouc_cmdr = 0;
    uint32 nouc_cmdw = 0;
    uint32 excp_cmdr = 0;
    uint32 excp_cmdw = 0;
    uint32 chan_id = 0;
    uint8 loop = 0;
    uint8 dest_chip_id = 0;
    uint16 dest_id = 0;
    uint8 cnt_hw = 0;
    uint8 step = 0;
    uint8 step1 = 0;
    uint32 lport;
    uint32 value[32] = {0};
    sys_usw_dmps_port_info_t dmps_port_info = {0};

    lport = CTC_MAP_GPORT_TO_LPORT(fail_port);

    uc_cmdr = DRV_IOR(PortLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
    uc_cmdw = DRV_IOW(PortLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
    uc_en_cmdr = DRV_IOR(PortLagLinkSelfHealingEn_t, PortLagLinkSelfHealingEn_enableBitmap_f);
    uc_en_cmdw = DRV_IOW(PortLagLinkSelfHealingEn_t, PortLagLinkSelfHealingEn_enableBitmap_f);
    nouc_cmdr = DRV_IOR(DsMetPortLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
    nouc_cmdw = DRV_IOW(DsMetPortLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
    if (DRV_FROM_AT(lchip))
    {
        excp_cmdr = DRV_IOR(DsMetExcpPortLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
        excp_cmdw = DRV_IOW(DsMetExcpPortLagLinkSelfHealingSet_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, excp_cmdr, &excp_self_healing));
    }

    if(0 == port_array->count)
    {
        /*clear backup member*/
        sal_memset(&uc_self_healing, 0, sizeof(PortLagLinkSelfHealingSet_m));
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, uc_cmdw, &uc_self_healing));

        CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, nouc_cmdr, &nouc_self_healing));
        chan_id = GetDsMetPortLagLinkSelfHealingSet(V, channelId_f, &nouc_self_healing);
        sal_memset(&nouc_self_healing, 0, sizeof(DsMetPortLagLinkSelfHealingSet_m));
        SetDsMetPortLagLinkSelfHealingSet(V, channelId_f, &nouc_self_healing, chan_id);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, nouc_cmdw, &nouc_self_healing));

        if (DRV_FROM_AT(lchip))
        {
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, excp_cmdr, &excp_self_healing));
            chan_id = GetDsMetExcpPortLagLinkSelfHealingSet(V, channelId_f, &excp_self_healing);
            sal_memset(&excp_self_healing, 0, sizeof(DsMetExcpPortLagLinkSelfHealingSet_m));
            SetDsMetExcpPortLagLinkSelfHealingSet(V, channelId_f, &excp_self_healing, chan_id);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, excp_cmdw, &excp_self_healing));
        }

        /*set disable*/
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, uc_en_cmdr, &value));
        CTC_BIT_UNSET(value[lport / 32], lport % 32);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, uc_en_cmdw, &value));
    }
    else
    {
        /*set backup member*/
        cnt_hw = 0;
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, uc_cmdr, &uc_self_healing));
        step = PortLagLinkSelfHealingSet_gMember_1_destChipId_f - PortLagLinkSelfHealingSet_gMember_0_destChipId_f;
        for(loop = 0; loop < port_array->count; loop++)
        {
            dest_chip_id = CTC_MAP_GPORT_TO_GCHIP(port_array->backup_ports[loop]);
            dest_id = CTC_MAP_GPORT_TO_LPORT(port_array->backup_ports[loop]);
            if(dest_chip_id == 0x1F)
            {
                continue;
            }
            else if (FALSE == sys_usw_chip_is_local(lchip, dest_chip_id))
            {
                chan_id = 0;
            }
            else
            {
                dmps_port_info.gport = port_array->backup_ports[loop];
                CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
                if(SYS_COMMON_USELESS_CHANNEL == chan_id)
                {
                    continue;
                }
            }
            DRV_SET_FIELD_V(lchip, PortLagLinkSelfHealingSet_t,
                            PortLagLinkSelfHealingSet_gMember_0_destChannel_f + cnt_hw * step,
                            &uc_self_healing, SYS_USW_CHANNEL_ENCODE(chan_id));
            DRV_SET_FIELD_V(lchip, PortLagLinkSelfHealingSet_t,
                            PortLagLinkSelfHealingSet_gMember_0_destChipId_f + cnt_hw * step,
                            &uc_self_healing, dest_chip_id);
            DRV_SET_FIELD_V(lchip, PortLagLinkSelfHealingSet_t,
                            PortLagLinkSelfHealingSet_gMember_0_destId_f + cnt_hw * step,
                            &uc_self_healing, dest_id);
            cnt_hw++;
        }
        SetPortLagLinkSelfHealingSet(V, setSize_f, &uc_self_healing, cnt_hw > 0 ? cnt_hw - 1 : 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, uc_cmdw, &uc_self_healing));

        cnt_hw = 0;
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, nouc_cmdr, &nouc_self_healing));
        step = DsMetPortLagLinkSelfHealingSet_gMember_1_destChipId_f - DsMetPortLagLinkSelfHealingSet_gMember_0_destChipId_f;
        step1 = DsMetExcpPortLagLinkSelfHealingSet_gMember_1_destChannelId_f - DsMetExcpPortLagLinkSelfHealingSet_gMember_0_destChannelId_f;
        for(loop = 0; loop < port_array->count; loop++)
        {
            dest_chip_id = CTC_MAP_GPORT_TO_GCHIP(port_array->backup_ports[loop]);
            if(dest_chip_id == 0x1F || FALSE == sys_usw_chip_is_local(lchip, dest_chip_id))
            {
                continue;
            }
            else
            {
                dmps_port_info.gport = port_array->backup_ports[loop];
                CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
                if(SYS_COMMON_USELESS_CHANNEL == chan_id)
                {
                    continue;
                }
            }
            dest_id = CTC_MAP_GPORT_TO_LPORT(port_array->backup_ports[loop]);
            DRV_SET_FIELD_V(lchip, DsMetPortLagLinkSelfHealingSet_t,
                            DsMetPortLagLinkSelfHealingSet_gMember_0_destChannelId_f + cnt_hw * step,
                            &nouc_self_healing, SYS_USW_CHANNEL_ENCODE(chan_id));
            DRV_SET_FIELD_V(lchip, DsMetPortLagLinkSelfHealingSet_t,
                            DsMetPortLagLinkSelfHealingSet_gMember_0_destChipId_f + cnt_hw * step,
                            &nouc_self_healing, dest_chip_id);
            DRV_SET_FIELD_V(lchip, DsMetPortLagLinkSelfHealingSet_t,
                            DsMetPortLagLinkSelfHealingSet_gMember_0_destId_f + cnt_hw * step,
                            &nouc_self_healing, dest_id);

            if (DRV_FROM_AT(lchip))
            {
                SetDsMetExcpPortLagLinkSelfHealingSet(V, gMember_0_destChannelId_f + cnt_hw*step1, &excp_self_healing, chan_id);
                SetDsMetExcpPortLagLinkSelfHealingSet(V, gMember_0_destChipId_f + cnt_hw*step1, &excp_self_healing, dest_chip_id);
                SetDsMetExcpPortLagLinkSelfHealingSet(V, gMember_0_destId_f + cnt_hw*step1, &excp_self_healing, dest_id);
            }
            cnt_hw++;
        }
        dmps_port_info.gport = fail_port;
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_id));
        SetDsMetPortLagLinkSelfHealingSet(V, channelId_f, &nouc_self_healing, cnt_hw > 0 ? SYS_USW_CHANNEL_ENCODE(chan_id) : 0);
        SetDsMetPortLagLinkSelfHealingSet(V, setSize_f, &nouc_self_healing, cnt_hw > 0 ? cnt_hw - 1 : 0);
        SetDsMetPortLagLinkSelfHealingSet(V, logToLagLinkSelfHealingEn_f, &nouc_self_healing, cnt_hw > 0 ? 1 : 0);
        SetDsMetPortLagLinkSelfHealingSet(V, nonUcastToLagLinkSelfHealingEn_f, &nouc_self_healing, cnt_hw > 0 ? 1 : 0);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, nouc_cmdw, &nouc_self_healing));
        if (DRV_FROM_AT(lchip))
        {
            SetDsMetExcpPortLagLinkSelfHealingSet(V, setSize_f, &excp_self_healing, cnt_hw > 0 ? cnt_hw - 1 : 0);
            SetDsMetExcpPortLagLinkSelfHealingSet(V, channelId_f, &excp_self_healing, cnt_hw > 0 ? chan_id : 0);
            SetDsMetExcpPortLagLinkSelfHealingSet(V, logToLagLinkSelfHealingEn_f, &excp_self_healing, cnt_hw > 0 ? 1 : 0);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, lport, excp_cmdw, &excp_self_healing));
        }

        /*set enable*/
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, uc_en_cmdr, &value));
        CTC_BIT_SET(value[lport / 32], lport % 32);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, uc_en_cmdw, &value));
    }
    return CTC_E_NONE;
}

int32
sys_tmm_linkagg_set_lsh(uint8 lchip, void* p_lag_group, uint32 fail_port, void* p_ports)
{
    int32 ret = CTC_E_NONE;
    uint8 next = 0;
    uint8 local = 0;
    uint8 dest_chip_id = 0;
    uint16 mem_idx = 0;
    uint16 i = 0;
    ctc_linkagg_lsh_t bkp;
    sys_linkagg_t* p_group = (sys_linkagg_t*)p_lag_group;
    ctc_linkagg_lsh_t* port_array = (ctc_linkagg_lsh_t*)p_ports;

    sal_memset(&bkp, 0, sizeof(ctc_linkagg_lsh_t));

    for(mem_idx = 0; mem_idx < p_group->port_cnt; mem_idx++)
    {
        if (fail_port == p_group->port_list[mem_idx]->gport)
        {
            break;
        }
    }

    if (mem_idx == p_group->port_cnt)
    {
        /* Port not in linkagg! */
        return CTC_E_NOT_EXIST;
    }

    dest_chip_id = SYS_MAP_CTC_GPORT_TO_GCHIP(fail_port);
    if (FALSE == sys_usw_chip_is_local(lchip, dest_chip_id))
    {
        return CTC_E_NONE;
    }

    bkp.backup_ports = mem_malloc(MEM_LINKAGG_MODULE, SYS_LINKAGG_LSH_PORTS_MAX * sizeof(uint32));
    if(!bkp.backup_ports)
    {
        SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "No memory!\n");
        ret = CTC_E_NO_MEMORY;
        goto out;
    }
    sal_memset(bkp.backup_ports, 0, SYS_LINKAGG_LSH_PORTS_MAX * sizeof(uint32));

    if(port_array->lsh_mode != CTC_LINKAGG_LSH_MODE_USERDEF)
    {
        switch (port_array->lsh_mode)
        {
            case CTC_LINKAGG_LSH_MODE_NEXT:
                local = FALSE;
                next = TRUE;
                break;
            case CTC_LINKAGG_LSH_MODE_NEXT_LOCAL:
                local = TRUE;
                next = TRUE;
                break;
            case CTC_LINKAGG_LSH_MODE_ALL:
                local = FALSE;
                next = FALSE;
                break;
            case CTC_LINKAGG_LSH_MODE_ALL_LOCAL:
                local = TRUE;
                next = FALSE;
                break;
            default:
                ret = CTC_E_INVALID_PARAM;
                goto out;
        }

        bkp.count = 0;

        for (i = ((mem_idx + 1) % p_group->port_cnt); /* Start after fail port */
            i != mem_idx;                   /* Stop after cycling around */
            i = ((i + 1) % p_group->port_cnt))
        { /* Cycle through trunk port list */

            if (local)
            {
                dest_chip_id = CTC_MAP_GPORT_TO_GCHIP(p_group->port_list[i]->gport);
                if (FALSE == sys_usw_chip_is_local(lchip, dest_chip_id))
                {
                    continue;
                }
            }

            bkp.backup_ports[bkp.count] = p_group->port_list[i]->gport;
            bkp.count++;

            if (bkp.count == SYS_LINKAGG_LSH_PORTS_MAX)
            {
                break;
            }
            if (next)
            {
                break;
            }
        }

    }
    else
    {
       if(port_array->count)
       {
           for (i = 0; i < port_array->count && i < SYS_LINKAGG_LSH_PORTS_MAX; i++)
           {
               bkp.backup_ports[i] = port_array->backup_ports[i];
           }
           bkp.count = i;
       }

    }

    CTC_ERROR_GOTO(_sys_tmm_linkagg_lsh_add_to_asic(lchip, fail_port, &bkp), ret, out);
out:
    if(bkp.backup_ports)
    {
        mem_free(bkp.backup_ports);
    }
    return CTC_E_NONE;

}

int32
sys_tmm_linkagg_channel_update_nonuc_ports(uint8 lchip, bool is_add_port, uint16 chan_id, uint32* mem_bmp)
{
    uint32 cmd = 0;
    uint16 index = 0;
    uint16 mem_old_array[32] = {0};
    uint16 mem_array[32] = {0};
    uint8 mem_old_cnt = 0;
    uint8 mem_cnt = 0;
    uint16 mem_chan = 0;
    uint16 chan_i = 0;
    uint8 hash = 0;
    uint8 mem_idx = 0;
    uint32 block_bitmap[CTC_PORT_BITMAP_IN_WORD] = {0};
    uint32 mem_bmp_tmp[CTC_PORT_BITMAP_IN_WORD] = {0};
    DsMetNonUcChanLagBlockMask_m block_mask;
    uint16 lport = 0;

    sal_memcpy(mem_bmp_tmp, mem_bmp, sizeof(mem_bmp_tmp));

    CTC_BMP_ITER_BEGIN(mem_bmp_tmp, chan_i)
    {
        mem_old_array[mem_old_cnt++] = chan_i;
    }
    CTC_BMP_ITER_END(mem_bmp_tmp, chan_i);

    is_add_port ? CTC_BMP_SET(mem_bmp_tmp, SYS_USW_CHANNEL_ENCODE(chan_id)) : CTC_BMP_UNSET(mem_bmp_tmp, SYS_USW_CHANNEL_ENCODE(chan_id));

    mem_cnt = 0;
    CTC_BMP_ITER_BEGIN(mem_bmp_tmp, chan_i)
    {
        mem_array[mem_cnt++] = chan_i;
    }
    CTC_BMP_ITER_END(mem_bmp_tmp, chan_i);

    for(index = 0; index < mem_cnt; index++)
    {
        cmd = DRV_IOW(DsMetPortChannelLag_t, DsMetPortChannelLag_channelBitmap_f);
        /*eloop and loop channel same 114, so cannot get lport with chan_id*/
        if (DRV_FROM_AT(lchip))
        {
            if ((mem_array[index] >= MCHIP_CAP(SYS_CAP_CHANID_ELOOP)) 
             && (mem_array[index] <  MCHIP_CAP(SYS_CAP_CHANID_ELOOP) + MCHIP_CAP(SYS_CAP_CHANID_LOOP_NUM)))
            {
                lport = MCHIP_CAP(SYS_CAP_RSV_PORT_ELOOP_ID) - (mem_array[index] - MCHIP_CAP(SYS_CAP_CHANID_ELOOP)) / 2;
            }
            else
            {
                lport = SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, mem_array[index]);
            }
        }
        else
        {
            uint16 chan_tmp = SYS_USW_CHANNEL_DECODE(mem_array[index]);
            if (chan_tmp == MCHIP_CAP(SYS_CAP_CHANID_ELOOP))
            {
                lport = MCHIP_CAP(SYS_CAP_RSV_PORT_ELOOP_ID);
            }
            else if (chan_tmp == MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM))
            {
                lport = MCHIP_CAP(SYS_CAP_RSV_PORT_ELOOP1_ID);
            }
            else
            {
                lport = SYS_GET_LPORT_ID_WITH_CHAN(lchip, 0, chan_tmp);
            }
        }
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, lport, cmd, mem_bmp_tmp));
        /*for loop channel, port and channel N:1*/
        if (!SYS_IS_NETWORK_CHANNEL(mem_array[index]))
        {
            break;
        }
    }

    for(hash = 0; hash < SYS_LINKAGG_CHAN_HASH_MAX && mem_cnt ;hash++)
    {
        cmd = DRV_IOR(DsMetNonUcChanLagBlockMask_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, hash, cmd, &block_mask));

        /*clear old member mask*/
        for(chan_i = 0; chan_i < mem_old_cnt; chan_i++)
        {
            mem_chan = mem_old_array[chan_i];
            GetDsMetNonUcChanLagBlockMask(A, chanBlockBitmap_f, &block_mask, &block_bitmap);
            CTC_BMP_UNSET(block_bitmap, mem_chan);
            SetDsMetNonUcChanLagBlockMask(A, chanBlockBitmap_f, &block_mask, &block_bitmap);
        }
        /*set new member mask*/
        mem_idx = hash % mem_cnt;
        for(chan_i = 0; chan_i < mem_cnt; chan_i++)
        {
            mem_chan = mem_array[chan_i];
            GetDsMetNonUcChanLagBlockMask(A, chanBlockBitmap_f, &block_mask, &block_bitmap);
            chan_i == mem_idx ? CTC_BMP_UNSET(block_bitmap, mem_chan) : CTC_BMP_SET(block_bitmap, mem_chan);
            SetDsMetNonUcChanLagBlockMask(A, chanBlockBitmap_f, &block_mask, &block_bitmap);
        }

        cmd = DRV_IOW(DsMetNonUcChanLagBlockMask_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, hash, cmd, &block_mask))

    }
    sal_memcpy(mem_bmp,mem_bmp_tmp, sizeof(mem_bmp_tmp));

    return CTC_E_NONE;
}

int32
sys_tmm_linkagg_bind_mirror(uint8 lchip, uint16 tid, uint8 is_add)
{
    sys_linkagg_t* p_group = NULL;

    p_group = ctc_vector_get(p_usw_linkagg_master[lchip]->group_vector, tid);
    if (!p_group)
    {
        return CTC_E_ENTRY_NOT_EXIST;
    }

    if (is_add)
    {
        p_group->mirror_ref_cnt++;
    }
    else if (0 != p_group->mirror_ref_cnt)
    {
        p_group->mirror_ref_cnt--;
    }
    else
    {
        return CTC_E_ENTRY_NOT_EXIST;
    }

    return CTC_E_NONE;
}

int32
sys_tmm_linkagg_loop_chan_lag_en(uint8 lchip, uint32 enable)
{
    int32 ret = CTC_E_NONE;
    ctc_linkagg_group_t chan_lag;
    uint8 tid = 0;
    uint32 lport = 0;
    uint32 cmd = 0;
    uint32 field_val = 0;
    DsPortChannelLag_m ds_chanagg_grp;

    if (!enable)
    {
        _sys_usw_linkagg_destroy_channel_agg(lchip, MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX)-2);
        _sys_usw_linkagg_destroy_channel_agg(lchip, MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX)-1);
        sal_memset(&ds_chanagg_grp, 0, sizeof(ds_chanagg_grp));
        cmd = DRV_IOW(DsPortChannelLag_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, MCHIP_CAP(SYS_CAP_RSV_PORT_ELOOP_ID), cmd, &ds_chanagg_grp);
        DRV_IOCTL(lchip, MCHIP_CAP(SYS_CAP_RSV_PORT_ELOOP1_ID), cmd, &ds_chanagg_grp);
        field_val = 0;
        cmd = DRV_IOW(DsMetPortChannelLag_t, DsMetPortChannelLag_chanLagEnable_f);
        DRV_FIELD_IOCTL(lchip, MCHIP_CAP(SYS_CAP_RSV_PORT_ELOOP_ID), cmd, &field_val);
        DRV_FIELD_IOCTL(lchip, MCHIP_CAP(SYS_CAP_RSV_PORT_ELOOP1_ID), cmd, &field_val);
        MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID) = MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID)+2;
        return CTC_E_NONE;
    }
    /*1. default create dp0(114&116), channel linkagg group*/
    tid = MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX)-1;
    sal_memset(&chan_lag, 0, sizeof(ctc_linkagg_group_t));
    chan_lag.tid = tid;
    chan_lag.linkagg_mode = CTC_LINKAGG_MODE_STATIC;
    CTC_ERROR_RETURN(_sys_usw_linkagg_create_channel_agg(lchip, &chan_lag));

    CTC_ERROR_GOTO(_sys_usw_linkagg_add_channel_member(lchip, tid, MCHIP_CAP(SYS_CAP_CHANID_ELOOP)), ret, roll_back_0);
    CTC_ERROR_GOTO(_sys_usw_linkagg_add_channel_member(lchip, tid, MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+2), ret, roll_back_0);
    lport = MCHIP_CAP(SYS_CAP_RSV_PORT_ELOOP_ID);
    sal_memset(&ds_chanagg_grp, 0, sizeof(ds_chanagg_grp));
    SetDsPortChannelLag(V, linkAggregationChannelGroup_f, &ds_chanagg_grp, tid);
    cmd = DRV_IOW(DsPortChannelLag_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, lport, cmd, &ds_chanagg_grp), ret, roll_back_0);
    field_val = 1;
    cmd = DRV_IOW(DsMetPortChannelLag_t, DsMetPortChannelLag_chanLagEnable_f);
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, lport, cmd, &field_val), ret, roll_back_0);

   /*1. default create  dp1(114&116), channel linkagg group*/
    tid = MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX)-2;
    sal_memset(&chan_lag, 0, sizeof(ctc_linkagg_group_t));
    chan_lag.tid = tid;
    chan_lag.linkagg_mode = CTC_LINKAGG_MODE_STATIC;
    CTC_ERROR_GOTO(_sys_usw_linkagg_create_channel_agg(lchip, &chan_lag), ret, roll_back_0);

    CTC_ERROR_GOTO(_sys_usw_linkagg_add_channel_member(lchip, tid, MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM)), ret, roll_back_1);
    CTC_ERROR_GOTO(_sys_usw_linkagg_add_channel_member(lchip, tid, MCHIP_CAP(SYS_CAP_CHANID_ELOOP)+2+MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM)), ret, roll_back_1);
    lport = MCHIP_CAP(SYS_CAP_RSV_PORT_ELOOP1_ID);
    sal_memset(&ds_chanagg_grp, 0, sizeof(ds_chanagg_grp));
    SetDsPortChannelLag(V, linkAggregationChannelGroup_f, &ds_chanagg_grp, tid);
    cmd = DRV_IOW(DsPortChannelLag_t, DRV_ENTRY_FLAG);
    CTC_ERROR_GOTO(DRV_IOCTL(lchip, lport, cmd, &ds_chanagg_grp), ret, roll_back_1);
    field_val = 1;
    cmd = DRV_IOW(DsMetPortChannelLag_t, DsMetPortChannelLag_chanLagEnable_f);
    CTC_ERROR_GOTO(DRV_FIELD_IOCTL(lchip, lport, cmd, &field_val), ret, roll_back_1);
    MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID) = MCHIP_CAP(SYS_CAP_STK_TRUNK_MAX_ID)-2;

    return CTC_E_NONE;
roll_back_1:
    _sys_usw_linkagg_destroy_channel_agg(lchip, MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX)-2);

roll_back_0:
    _sys_usw_linkagg_destroy_channel_agg(lchip, MCHIP_CAP(SYS_CAP_LINKAGG_CHAN_GRP_MAX)-1);
    return ret;
}

#endif

